package com.javabi.common.concurrent.looping;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

import com.google.common.base.Throwables;

public class LoopingRunner implements ILoopingRunner {

	private final Runnable runnable;
	private final AtomicBoolean shutdown = new AtomicBoolean(false);
	private final AtomicReference<Throwable> throwable = new AtomicReference<Throwable>(null);

	public LoopingRunner(Runnable runnable) {
		if (runnable == null) {
			throw new NullPointerException("runnable");
		}
		this.runnable = runnable;
	}

	@Override
	public void run() {
		try {
			while (!shutdown.get()) {
				runnable.run();
			}
		} catch (Throwable t) {
			throwable.set(t);
			handleThrowable(t);
		} finally {
			shutdown.set(true);
		}
	}

	/**
	 * Override this method to handle any throwable during the run.
	 */
	protected void handleThrowable(Throwable throwable) {
		throw Throwables.propagate(throwable);
	}

	@Override
	public boolean isShutdown() {
		return shutdown.get();
	}

	@Override
	public void shutdown() {
		shutdown.set(true);
	}

	@Override
	public Throwable getThrowable() {
		return throwable.get();
	}

}
